package observer

import "fmt"

// 实现Subject接口以及ConcreteSuject
type Subject interface {
	SetState(state string)
	GetState() string
	Attach(observer Observer)
	Notify()
}

type Boss struct {
	observer []Observer
	state    string
}

func (b *Boss) SetState(state string) {
	b.state = state
}

func (b Boss) GetState() string {
	return b.state
}

func (b *Boss) Attach(observer Observer) {
	b.observer = append(b.observer, observer)
}

func (b *Boss) Notify() {
	for _, o := range b.observer {
		o.Update()
	}
}

type Secretary struct {
	observer []Observer
	state    string
}

func (s *Secretary) SetState(state string) {
	s.state = state
}

func (s Secretary) GetState() string {
	return s.state
}

func (s *Secretary) Attach(observer Observer) {
	s.observer = append(s.observer, observer)
}

func (s *Secretary) Notify() {
	for _, o := range s.observer {
		o.Update()
	}
}

// 实现Observer接口以及ConcreteObserver
type Observer interface {
	Update()
}

type StockObserver struct {
	name    string
	subject Subject
}

func (so StockObserver) Update() {
	fmt.Printf("%s, %s 关闭炒股软件，开始工作\n", so.subject.GetState(), so.name)
}

type NBAObserver struct {
	name    string
	subject Subject
}

func (no NBAObserver) Update() {
	fmt.Printf("%s, %s 关闭NBA直播，开始工作\n", no.subject.GetState(), no.name)
}

// 使用工厂方法创建具体观察者和被观察者
func NewSubject(t string) Subject {
	switch t {
	case "boss":
		return &Boss{}
	case "secretary":
		return &Secretary{}
	default:
		return nil
	}
}

func NewObserver(t, name string, subject Subject) Observer {
	switch t {
	case "stock":
		return &StockObserver{
			name:    name,
			subject: subject,
		}
	case "nba":
		return &NBAObserver{
			name:    name,
			subject: subject,
		}
	default:
		return nil
	}
}
